#pragma once
#include "Socket.hpp"
#include "InetAddr.hpp"
#include <functional>
// 设置函数对象

using namespace socket_ns;
static const int gport = 8888;

using service_t = std::function<std::string(std::string &resqueststr)>;

class TcpServer
{

public:
  TcpServer(service_t service, uint16_t port = gport)
      : _port(port), _listensock(std::make_shared<TcpSocket>()), _isrunning(false), _service(service)
  {
    _listensock->BuildListenSocket(_port);
  }

  class ThreadData
  {
  public:
    SockSPtr _sockfd;
    TcpServer *_self;
    InetAddr _addr; // 给InetAddr再添加一个无参构造
  public:
    ThreadData(SockSPtr sockfd, TcpServer *self, const InetAddr &addr) : _sockfd(sockfd), _self(self), _addr(addr)
    {
    }
  };

  void Loop()
  {
    // signal(SIGCHLD, SIG_IGN);
    _isrunning = true;
    while (_isrunning)
    {
      InetAddr client;
      SockSPtr newsock = _listensock->Accepter(&client);
      if (newsock == nullptr)
      {
        continue;
      }

      LOG(INFO, "get a new link, client info : %s, sockfd is: %d\n", client.AddrStr().c_str(), newsock->Sockfd());

      // version2-----多线程版本 --- 不能关闭fd,也不需要
      pthread_t tid;
      ThreadData *td = new ThreadData(newsock, this, client);
      pthread_create(&tid, nullptr, Execute, td);
    }
    _isrunning = false;
  }
            //执行
  static void *Execute(void *args)
  {
    pthread_detach(pthread_self());

    ThreadData *td = static_cast<ThreadData *>(args);

    std::string requeststr;

    // 我们后面不做请求的分离了，我们认为我们读到的是一个完整的请求--bug
    ssize_t n = td->_sockfd->Recv(&requeststr);
    if (n > 0)
    {
      // 直接回调我们定义的函数对象，把请求字符串给我，我在service进行处理
      std::string responsestr = td->_self->_service(requeststr);
      //返回一个序列化之后的responsestr
      td->_sockfd->Send(responsestr); 
    }

    // 处理完了，直接关闭
    td->_sockfd->Close();

    delete td;
    return nullptr;
  }

  ~TcpServer()
  {
  }

private:
  uint16_t _port;
  //   int _listensockfd;
  //   定义套接字对象
  SockSPtr _listensock;
  bool _isrunning;
  service_t _service;
};
